#pragma once

#include <iostream>
#include <memory>
#include <sys/epoll.h>
#include "Socket.hpp"
#include "log.hpp"
#include "nocopy.hpp"

// epoll: 是为了处理大批量句柄而作了改进的poll
class Epoller:public nocopy
{
    static const int size = 128;
public:
    Epoller(int timeout = 3000)
        :_timeout(timeout)
    {
        // epoll_create:创建一个epoll的句柄
        // 返回epoll实例的文件描述符
        _epfd = epoll_create(size);
        if(_epfd == -1)
        {
            lg(Error,"epoll_create error: %s",strerror(errno));
        }
        else
        {
            lg(Info,"epoll_create success: %d",_epfd);
        }
    }
    ~Epoller()
    {
        if(_epfd >= 0)
            close(_epfd);
    }
    // 收集事件
    int EpollerWait(struct epoll_event revents[],int num)
    {
        // epoll_wait:收集epoll监控的事件中已经发送的事件
        int n = epoll_wait(_epfd,revents,num,/*_timeout*/-1);
        return n;
    }
    // 更新
    int EpollerUpdate(int oper,int sock,uint32_t event)
    {
        int n = 0;
        // EPOLL_CTL_DEL:从epfd中删除一个fd
        if(oper == EPOLL_CTL_DEL)
        {
            // epoll_ctl:控制epfd
            n = epoll_ctl(_epfd,oper,sock,nullptr);
            if(n != 0)
            {
                lg(Error,"epoll_ctl delete error!");
            }
        }
        else
        {
            // EPOLL_CTL_MOD || EPOLL_CTL_ADD
            // EPOLL_CTL_MOD:修改已经注册的fd的监听事件
            // EPOLL_CTL_ADD:注册新的fd到epfd中
            struct epoll_event ev;
            ev.events = event;
            ev.data.fd = sock;

            n = epoll_ctl(_epfd,oper,sock,&ev);
            if(n != 0)
            {
                lg(Error,"epoll_ctl error!");
            }
        }
        return n;
    }

private:
    int _epfd;
    int _timeout;
};